data sources
GPU benchmarks: https://www.userbenchmark.com/page/developer
CPU benchmarks: https://browser.geekbench.com/opencl-benchmarks
GPU and CPU prices: https://pcpartpicker.com/

library(shiny)
library(tidyverse)
library(plotly)
library(ggrepel)

gfx  <- read_csv("GPU_UserBenchmarks.csv")
pcpp <- read_csv("pcpartpicker.com-(Crawl-Run)---2020-07-20T010546Z.csv")
gfx$model_tidy <- NA
pcpp <- pcpp %>% 
  mutate(Chipset_mod = gsub("GeForce |Radeon ", "", Chipset))

for (i in unique(pcpp$Chipset_mod)) {
  row_hits <- grep(paste0("\\b", i, "\\b"), 
                   gfx$Model, 
                   ignore.case = TRUE)
  if (length(row_hits) > 0) {
    gfx$model_tidy[row_hits] <- 
      c(rep(i, length(row_hits)))
  }
}

left_join(gfx, pcpp, by = c("model_tidy" = "Chipset_mod")) %>% 
  select(model_tidy, Benchmark, Price, Samples) %>% 
  group_by(model_tidy) %>% distinct() %>% 
  arrange(desc(model_tidy, Price)) %>% slice(n()) %>% drop_na() %>% 
  ungroup() %>% mutate(Price = as.numeric(gsub("[$]|\\..*", "", Price))) %>%
  mutate(`Score/dollar` = Benchmark/Price) %>%
  ggplot(aes(x     = Benchmark, 
             y     = `Score/dollar`, 
             color = Benchmark,
             size  = Samples)) + 
  geom_point() + 
  geom_text_repel(
    aes(label = ifelse(Benchmark > 50 | `Score/dollar` > 0.15, 
                       paste0(model_tidy, " (", Price, " USD)"),
                       '')), 
    hjust = 0, vjust = 0,
    size = 3) + 
  scale_color_gradient(low = "black", high = "red") + 
  guides(color = FALSE) + 
  labs(x        = "UserBenchmark Score", 
       y        = "Score / Dollar",
       title    = "GPU Performance Per Dollar",
       subtitle = "Prices from PC Partpicker (July 2020)") +
  scale_x_continuous(trans = "log10") + 
  theme_light()

cpu_geek <- read_csv("browser.geekbench.com-(Crawl-Run)---2020-07-20T044700Z.csv")
cpu_pcpp <- read_csv("pcpartpicker.com-(Crawl-Run)---2020-07-20T045353Z.csv")

cpu_geek <- cpu_geek %>% mutate(CPU = toupper(Processor))
cpu_pcpp <- cpu_pcpp %>% mutate(CPU = toupper(`Name Wrapper`))
cpus <- left_join(cpu_geek, cpu_pcpp, by = "CPU") %>% 
    select(CPU, Score, Price, `Speed (Cores)`) %>% drop_na() %>% 
    group_by(CPU) %>% arrange(desc(CPU, Score)) %>% slice(1) %>% 
    ungroup() %>% mutate(Price = as.numeric(gsub("[$]|\\..*", "", Price))) %>% 
    mutate(`Score/Dollar` = Score/Price,
           CPU = str_to_title(CPU)) %>% 
    separate(`Speed (Cores)`, 
             sep = " GHz ", 
             into = c("Speed (GHz)", "Cores")) %>% 
    mutate(Cores = as.numeric(gsub("\\(| cores\\)", "", Cores)), 
           `Speed (GHz)` = as.numeric(`Speed (GHz)`),
           Processor = paste0(CPU, " (", `Speed (GHz)`, " GHz)"))

cpus %>%
  filter(Cores >= 8,
         `Speed (GHz)` >= 3) %>%
  ggplot(aes(x     = reorder(Processor, `Score/Dollar`), 
             y     = `Score/Dollar`, 
             fill  = Score)) + 
  geom_bar(stat = "identity") +
  guides(color = FALSE) + 
  labs(x        = "Processor", 
       y        = "Geekbench Score / Dollar",
       title    = "CPU Performance Per Dollar (Single Core, 8+ Cores)",
       subtitle = "Prices from PC Partpicker (July 2020)") +
  coord_flip() +
  theme_light()

cpus %>%
  filter(Cores < 8,
         `Score/Dollar` >= 5,
         `Speed (GHz)` >= 3) %>%
  ggplot(aes(x     = reorder(Processor, `Score/Dollar`), 
             y     = `Score/Dollar`, 
             fill  = Score)) + 
  geom_bar(stat = "identity") +
  guides(color = FALSE) + 
  labs(x        = "Processor", 
       y        = "Geekbench Score / Dollar",
       title    = "CPU Performance Per Dollar (Single Core, < 8 Cores)",
       subtitle = "Prices from PC Partpicker (July 2020)") +
  coord_flip() +
  theme_light()

(cpus %>%
  filter(`Speed (GHz)` >= 3.3,
         Cores >= 4) %>%
  ggplot(aes(x     = Score,
             y     = `Speed (GHz)`,
             color = `Score/Dollar`,
             label = CPU)) +
  geom_point() +
  labs(x = "Geekbench Score",
       y = "Speed (GHz)") +
  scale_color_gradient(low = "black", high = "red") +
  theme_light()) %>%
  ggplotly() %>%
  layout(title = list(text = paste0('CPU Performance Per Dollar (Single Core, 4+ Cores)',
                                    '<br>',
                                    '<sup>',
                                    'Prices from PC Partpicker (July 2020)',
                                    '</sup>')),
         margin = 1)
LS0tDQp0aXRsZTogIkNQVSAvIEdQVSBQZXJmb3JtYW5jZSBQZXIgUHJpY2UiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KKipkYXRhIHNvdXJjZXMqKiAgDQpHUFUgYmVuY2htYXJrczogaHR0cHM6Ly93d3cudXNlcmJlbmNobWFyay5jb20vcGFnZS9kZXZlbG9wZXIgIA0KQ1BVIGJlbmNobWFya3M6IGh0dHBzOi8vYnJvd3Nlci5nZWVrYmVuY2guY29tL29wZW5jbC1iZW5jaG1hcmtzICANCkdQVSBhbmQgQ1BVIHByaWNlczogaHR0cHM6Ly9wY3BhcnRwaWNrZXIuY29tLw0KDQpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHNoaW55KQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZ2dyZXBlbCkNCg0KZ2Z4ICA8LSByZWFkX2NzdigiR1BVX1VzZXJCZW5jaG1hcmtzLmNzdiIpDQpwY3BwIDwtIHJlYWRfY3N2KCJwY3BhcnRwaWNrZXIuY29tLShDcmF3bC1SdW4pLS0tMjAyMC0wNy0yMFQwMTA1NDZaLmNzdiIpDQpgYGANCg0KDQoNCmBgYHtyIGVjaG89VFJVRSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpnZngkbW9kZWxfdGlkeSA8LSBOQQ0KcGNwcCA8LSBwY3BwICU+JSANCiAgbXV0YXRlKENoaXBzZXRfbW9kID0gZ3N1YigiR2VGb3JjZSB8UmFkZW9uICIsICIiLCBDaGlwc2V0KSkNCg0KZm9yIChpIGluIHVuaXF1ZShwY3BwJENoaXBzZXRfbW9kKSkgew0KICByb3dfaGl0cyA8LSBncmVwKHBhc3RlMCgiXFxiIiwgaSwgIlxcYiIpLCANCiAgICAgICAgICAgICAgICAgICBnZngkTW9kZWwsIA0KICAgICAgICAgICAgICAgICAgIGlnbm9yZS5jYXNlID0gVFJVRSkNCiAgaWYgKGxlbmd0aChyb3dfaGl0cykgPiAwKSB7DQogICAgZ2Z4JG1vZGVsX3RpZHlbcm93X2hpdHNdIDwtIA0KICAgICAgYyhyZXAoaSwgbGVuZ3RoKHJvd19oaXRzKSkpDQogIH0NCn0NCg0KbGVmdF9qb2luKGdmeCwgcGNwcCwgYnkgPSBjKCJtb2RlbF90aWR5IiA9ICJDaGlwc2V0X21vZCIpKSAlPiUgDQogIHNlbGVjdChtb2RlbF90aWR5LCBCZW5jaG1hcmssIFByaWNlLCBTYW1wbGVzKSAlPiUgDQogIGdyb3VwX2J5KG1vZGVsX3RpZHkpICU+JSBkaXN0aW5jdCgpICU+JSANCiAgYXJyYW5nZShkZXNjKG1vZGVsX3RpZHksIFByaWNlKSkgJT4lIHNsaWNlKG4oKSkgJT4lIGRyb3BfbmEoKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgbXV0YXRlKFByaWNlID0gYXMubnVtZXJpYyhnc3ViKCJbJF18XFwuLioiLCAiIiwgUHJpY2UpKSkgJT4lDQogIG11dGF0ZShgU2NvcmUvZG9sbGFyYCA9IEJlbmNobWFyay9QcmljZSkgJT4lDQogIGdncGxvdChhZXMoeCAgICAgPSBCZW5jaG1hcmssIA0KICAgICAgICAgICAgIHkgICAgID0gYFNjb3JlL2RvbGxhcmAsIA0KICAgICAgICAgICAgIGNvbG9yID0gQmVuY2htYXJrLA0KICAgICAgICAgICAgIHNpemUgID0gU2FtcGxlcykpICsgDQogIGdlb21fcG9pbnQoKSArIA0KICBnZW9tX3RleHRfcmVwZWwoDQogICAgYWVzKGxhYmVsID0gaWZlbHNlKEJlbmNobWFyayA+IDUwIHwgYFNjb3JlL2RvbGxhcmAgPiAwLjE1LCANCiAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKG1vZGVsX3RpZHksICIgKCIsIFByaWNlLCAiIFVTRCkiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgJycpKSwgDQogICAgaGp1c3QgPSAwLCB2anVzdCA9IDAsDQogICAgc2l6ZSA9IDMpICsgDQogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdyA9ICJibGFjayIsIGhpZ2ggPSAicmVkIikgKyANCiAgZ3VpZGVzKGNvbG9yID0gRkFMU0UpICsgDQogIGxhYnMoeCAgICAgICAgPSAiVXNlckJlbmNobWFyayBTY29yZSIsIA0KICAgICAgIHkgICAgICAgID0gIlNjb3JlIC8gRG9sbGFyIiwNCiAgICAgICB0aXRsZSAgICA9ICJHUFUgUGVyZm9ybWFuY2UgUGVyIERvbGxhciIsDQogICAgICAgc3VidGl0bGUgPSAiUHJpY2VzIGZyb20gUEMgUGFydHBpY2tlciAoSnVseSAyMDIwKSIpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIikgKyANCiAgdGhlbWVfbGlnaHQoKQ0KYGBgDQoNCmBgYHtyIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmNwdV9nZWVrIDwtIHJlYWRfY3N2KCJicm93c2VyLmdlZWtiZW5jaC5jb20tKENyYXdsLVJ1biktLS0yMDIwLTA3LTIwVDA0NDcwMFouY3N2IikNCmNwdV9wY3BwIDwtIHJlYWRfY3N2KCJwY3BhcnRwaWNrZXIuY29tLShDcmF3bC1SdW4pLS0tMjAyMC0wNy0yMFQwNDUzNTNaLmNzdiIpDQoNCmNwdV9nZWVrIDwtIGNwdV9nZWVrICU+JSBtdXRhdGUoQ1BVID0gdG91cHBlcihQcm9jZXNzb3IpKQ0KY3B1X3BjcHAgPC0gY3B1X3BjcHAgJT4lIG11dGF0ZShDUFUgPSB0b3VwcGVyKGBOYW1lIFdyYXBwZXJgKSkNCmBgYA0KDQpgYGB7ciBlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KY3B1cyA8LSBsZWZ0X2pvaW4oY3B1X2dlZWssIGNwdV9wY3BwLCBieSA9ICJDUFUiKSAlPiUgDQogICAgc2VsZWN0KENQVSwgU2NvcmUsIFByaWNlLCBgU3BlZWQgKENvcmVzKWApICU+JSBkcm9wX25hKCkgJT4lIA0KICAgIGdyb3VwX2J5KENQVSkgJT4lIGFycmFuZ2UoZGVzYyhDUFUsIFNjb3JlKSkgJT4lIHNsaWNlKDEpICU+JSANCiAgICB1bmdyb3VwKCkgJT4lIG11dGF0ZShQcmljZSA9IGFzLm51bWVyaWMoZ3N1YigiWyRdfFxcLi4qIiwgIiIsIFByaWNlKSkpICU+JSANCiAgICBtdXRhdGUoYFNjb3JlL0RvbGxhcmAgPSBTY29yZS9QcmljZSwNCiAgICAgICAgICAgQ1BVID0gc3RyX3RvX3RpdGxlKENQVSkpICU+JSANCiAgICBzZXBhcmF0ZShgU3BlZWQgKENvcmVzKWAsIA0KICAgICAgICAgICAgIHNlcCA9ICIgR0h6ICIsIA0KICAgICAgICAgICAgIGludG8gPSBjKCJTcGVlZCAoR0h6KSIsICJDb3JlcyIpKSAlPiUgDQogICAgbXV0YXRlKENvcmVzID0gYXMubnVtZXJpYyhnc3ViKCJcXCh8IGNvcmVzXFwpIiwgIiIsIENvcmVzKSksIA0KICAgICAgICAgICBgU3BlZWQgKEdIeilgID0gYXMubnVtZXJpYyhgU3BlZWQgKEdIeilgKSwNCiAgICAgICAgICAgUHJvY2Vzc29yID0gcGFzdGUwKENQVSwgIiAoIiwgYFNwZWVkIChHSHopYCwgIiBHSHopIikpDQoNCmNwdXMgJT4lDQogIGZpbHRlcihDb3JlcyA+PSA4LA0KICAgICAgICAgYFNwZWVkIChHSHopYCA+PSAzKSAlPiUNCiAgZ2dwbG90KGFlcyh4ICAgICA9IHJlb3JkZXIoUHJvY2Vzc29yLCBgU2NvcmUvRG9sbGFyYCksIA0KICAgICAgICAgICAgIHkgICAgID0gYFNjb3JlL0RvbGxhcmAsIA0KICAgICAgICAgICAgIGZpbGwgID0gU2NvcmUpKSArIA0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBndWlkZXMoY29sb3IgPSBGQUxTRSkgKyANCiAgbGFicyh4ICAgICAgICA9ICJQcm9jZXNzb3IiLCANCiAgICAgICB5ICAgICAgICA9ICJHZWVrYmVuY2ggU2NvcmUgLyBEb2xsYXIiLA0KICAgICAgIHRpdGxlICAgID0gIkNQVSBQZXJmb3JtYW5jZSBQZXIgRG9sbGFyIChTaW5nbGUgQ29yZSwgOCsgQ29yZXMpIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJQcmljZXMgZnJvbSBQQyBQYXJ0cGlja2VyIChKdWx5IDIwMjApIikgKw0KICBjb29yZF9mbGlwKCkgKw0KICB0aGVtZV9saWdodCgpDQpgYGANCmBgYHtyIGVjaG89VFJVRSwgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTh9DQpjcHVzICU+JQ0KICBmaWx0ZXIoQ29yZXMgPCA4LA0KICAgICAgICAgYFNjb3JlL0RvbGxhcmAgPj0gNSwNCiAgICAgICAgIGBTcGVlZCAoR0h6KWAgPj0gMykgJT4lDQogIGdncGxvdChhZXMoeCAgICAgPSByZW9yZGVyKFByb2Nlc3NvciwgYFNjb3JlL0RvbGxhcmApLCANCiAgICAgICAgICAgICB5ICAgICA9IGBTY29yZS9Eb2xsYXJgLCANCiAgICAgICAgICAgICBmaWxsICA9IFNjb3JlKSkgKyANCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgZ3VpZGVzKGNvbG9yID0gRkFMU0UpICsgDQogIGxhYnMoeCAgICAgICAgPSAiUHJvY2Vzc29yIiwgDQogICAgICAgeSAgICAgICAgPSAiR2Vla2JlbmNoIFNjb3JlIC8gRG9sbGFyIiwNCiAgICAgICB0aXRsZSAgICA9ICJDUFUgUGVyZm9ybWFuY2UgUGVyIERvbGxhciAoU2luZ2xlIENvcmUsIDwgOCBDb3JlcykiLA0KICAgICAgIHN1YnRpdGxlID0gIlByaWNlcyBmcm9tIFBDIFBhcnRwaWNrZXIgKEp1bHkgMjAyMCkiKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHRoZW1lX2xpZ2h0KCkNCmBgYA0KDQoNCmBgYHtyIGVjaG89VFJVRSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9DQooY3B1cyAlPiUNCiAgZmlsdGVyKGBTcGVlZCAoR0h6KWAgPj0gMy4zLA0KICAgICAgICAgQ29yZXMgPj0gNCkgJT4lDQogIGdncGxvdChhZXMoeCAgICAgPSBTY29yZSwNCiAgICAgICAgICAgICB5ICAgICA9IGBTcGVlZCAoR0h6KWAsDQogICAgICAgICAgICAgY29sb3IgPSBgU2NvcmUvRG9sbGFyYCwNCiAgICAgICAgICAgICBsYWJlbCA9IENQVSkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgbGFicyh4ID0gIkdlZWtiZW5jaCBTY29yZSIsDQogICAgICAgeSA9ICJTcGVlZCAoR0h6KSIpICsNCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImJsYWNrIiwgaGlnaCA9ICJyZWQiKSArDQogIHRoZW1lX2xpZ2h0KCkpICU+JQ0KICBnZ3Bsb3RseSgpICU+JQ0KICBsYXlvdXQodGl0bGUgPSBsaXN0KHRleHQgPSBwYXN0ZTAoJ0NQVSBQZXJmb3JtYW5jZSBQZXIgRG9sbGFyIChTaW5nbGUgQ29yZSwgNCsgQ29yZXMpJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8c3VwPicsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnUHJpY2VzIGZyb20gUEMgUGFydHBpY2tlciAoSnVseSAyMDIwKScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPC9zdXA+JykpLA0KICAgICAgICAgbWFyZ2luID0gMSkNCmBgYA0KDQo=